package com.itxuhang.adapter;

import com.itxuhang.annotation.ResponseBody;
import com.itxuhang.handler.HandlerMethod;
import com.itxuhang.model.ModelAndView;
import com.itxuhang.resolver.IntegerTypeHandler;
import com.itxuhang.resolver.StringTypeHandler;
import com.itxuhang.resolver.TypeHandler;
import com.itxuhang.utils.JsonUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class RequestMappingHandlerAdapter implements HandlerAdapter{
    private List<TypeHandler> typeHandlers = new ArrayList<>();
    public RequestMappingHandlerAdapter() {
        typeHandlers.add(new IntegerTypeHandler());
        typeHandlers.add(new StringTypeHandler());
    }

    @Override
    public boolean supports(Object handler) {
        return (handler instanceof HandlerMethod);
    }

    @Override
    public ModelAndView handleRequest(Object handler, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HandlerMethod hm = (HandlerMethod)handler;
        Object controller = hm.getHandler();
        Method method = hm.getMethod();

        // 请求参数：http://localhost:8080/user/query?id=10&name=lisi
        Object[] args = handleParameters(req,controller,method);

        try {
            Object returnValue = method.invoke(controller,args);
            // 处理返回结果
            handleReturnValue(returnValue,method,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private void handleReturnValue(Object returnValue, Method method, HttpServletResponse resp) throws Exception {
        // 判断方法信息中是否有ResponseBody注解
        if(method.isAnnotationPresent(ResponseBody.class)){
            Class<?> returnType = method.getReturnType();
            if (returnType == String.class){
                resp.setContentType("text/plain;charset=utf-8");
                resp.getWriter().println(returnValue.toString());

            }else{
                resp.setContentType("application/json;charset=utf-8");
                // 将对象编程JSON字符串
                resp.getWriter().println(JsonUtils.object2Json(returnValue));
            }
        }else{
            //视图处理
        }

    }

    private Object[] handleParameters(HttpServletRequest req, Object controller, Method method) {
        List<Object> paramList = new ArrayList<>();

        // 请求参数集合，key就是请求参数名称，value是一个数组
        Map<String, String[]> parameterMap = req.getParameterMap();

        // 方法中的参数
        Parameter[] parameters = method.getParameters();

        Object value = null;
        for (Parameter parameter : parameters) {
            // name值其实是通过class文件中的信息得来的
            // 但是class文件中如果不做特殊处理，方法参数名字，一般都是arg0,arg1
            // 这个名字是和源码中方法名字不一样的，也无法去请求参数中找到对应的值
            String name = parameter.getName();
            Class<?> parameterType = parameter.getType();
            // 获取请求URL中的value
            String[] strings = parameterMap.get(name);
            value = resolveValue(parameterType,strings);
            paramList.add(value);
        }

        return paramList.toArray();
    }

    private Object resolveValue(Class<?> parameterType, String[] strings) {
        for (TypeHandler typeHandler : typeHandlers) {
            if (typeHandler.supports(parameterType)){
                return typeHandler.resolve(strings);
            }
        }
        return null;
    }
}
